<html lang="en">

<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>内存管理 - bravo</title>
<link rel="shortcut icon" href="https://JoyZgq.github.io/favicon.ico">
<link href="https://cdn.jsdelivr.net/npm/remixicon@2.2.0/fonts/remixicon.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/animate.css@3.7.2/animate.min.css">
<link rel="stylesheet" href="https://JoyZgq.github.io/media/css/tailwind.css">
<link rel="stylesheet" href="https://JoyZgq.github.io/styles/main.css">
<link rel="alternate" type="application/atom+xml" title="内存管理 - bravo - Atom Feed" href="https://JoyZgq.github.io/atom.xml">


  <script async src="https://www.googletagmanager.com/gtag/js?id=UA-164181119-1"></script>
  <script>
    window.dataLayer = window.dataLayer || [];
    function gtag(){dataLayer.push(arguments);}
    gtag('js', new Date());
  
    gtag('config', 'UA-164181119-1');
  </script>
    

  <meta name="description" content="运行时数据区



程序计数器

定义：当前线程所执行的字节码的行号指示器



  字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令，它是程序控制流的指示器，分支、循环、跳转、异常处理、线程恢复等基础功能都需要..." />
  <meta property="og:title" content="内存管理 - bravo">
  <meta property="og:description" content="运行时数据区



程序计数器

定义：当前线程所执行的字节码的行号指示器



  字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令，它是程序控制流的指示器，分支、循环、跳转、异常处理、线程恢复等基础功能都需要..." />
  <meta property="og:type" content="articles">
  <meta property="og:url" content="https://JoyZgq.github.io/post/NJDSCDD/" />
  <meta property="og:image" content="https://JoyZgq.github.io/post-images/NJDSCDD.webp">
  <meta property="og:image:height" content="630">
  <meta property="og:image:width" content="1200">
  <meta name="twitter:title" content="内存管理 - bravo">
  <meta name="twitter:description" content="运行时数据区



程序计数器

定义：当前线程所执行的字节码的行号指示器



  字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令，它是程序控制流的指示器，分支、循环、跳转、异常处理、线程恢复等基础功能都需要...">
  <meta name="twitter:card" content="summary_large_image">
  <link rel="canonical" href="https://JoyZgq.github.io/post/NJDSCDD/">

  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/default-skin/default-skin.css">
 
  
    <link rel="stylesheet" href="https://JoyZgq.github.io/media/css/prism-github.css">
  

  
</head>

<body>
  <div class="antialiased flex flex-col min-h-screen" id="app">
    <a href="https://JoyZgq.github.io" class="fixed top-0 left-0 mt-4 bg-black text-white dark:text-gray-700 dark:bg-yellow-50 dark:hover:bg-black dark:hover:text-white inline-flex p-2 pl-8 hover:text-gray-700 hover:bg-yellow-50 font-bold z-10 transition-fast animated fadeInLeft">
      bravo
    </a>
    <div class="max-w-4xl w-full mx-auto">
      <div class="shadow-box bg-white dark:bg-gray-600 rounded-lg pt-32 md:pt-64 px-4 md:px-8 pb-8 animated fadeIn mb-8">
        <h1 class="text-5xl font-semibold leading-normal pb-8 mb-8 border-b-8 border-gray-700">
          内存管理
        </h1>
        
          <img src="https://JoyZgq.github.io/post-images/NJDSCDD.webp" alt="内存管理" class="block w-full mb-8">
        
        <div class="mb-8 flex flex-wrap">
          <div class="text-gray-400 text-sm mr-4">2019-12-13 · 9 min read</div>
          
            <a href="https://JoyZgq.github.io/tag/o2fzfRk1O/" class="text-gray-700 text-sm border-b-2 border-dotted border-gray-200 hover:border-gray-600 transition-all duration-100 inline-flex mr-2">
              <i class="ri-hashtag"></i>
              jvm
            </a>
          
        </div>
        <div class="markdown mb-8" v-pre>
          <h3 id="运行时数据区">运行时数据区</h3>
<figure data-type="image" tabindex="1"><img src="https://JoyZgq.github.io/post-images/1587698912833.png" alt="" loading="lazy"></figure>
<ul>
<li>
<h4 id="程序计数器">程序计数器</h4>
<blockquote>
<p>定义：当前线程所执行的字节码的行号指示器</p>
</blockquote>
</li>
</ul>
<p>  字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令，它是程序控制流的指示器，分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成,为了线程切换后能恢复到正确的执行位置，每条线程都需要有一个独立的程序计数器，各条线程之间计数器互不影响,故是线程私有。</p>
<p>​  <em>此内存区域是唯一一个在《Java虚拟机规范》中没有规定任何<code>OutOfMemoryError</code>情况的区域。</em></p>
<ul>
<li>
<h4 id="java虚拟机栈">Java虚拟机栈</h4>
<blockquote>
<p>定义：Java虚拟机栈<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup>描述Java方法执行的线程内存模型：每个方法被执行的时候，Java虚拟机都会同步创建一个栈帧（Stack Frame）用于存储局部变量表<sup class="footnote-ref"><a href="#fn2" id="fnref2">[2]</a></sup>、操作数栈、动态连接、方法出口等信息。每一个方法被调用直至执行完毕的过程，就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。</p>
</blockquote>
</li>
</ul>
<p>  这些数据类型在局部变量表中的存储空间以局部变量槽（Slot）来表示，其中64位长度的long和double类型的数据会占用两个变量槽，其余的数据类型只占用一个。局部变量表所需的内存空间在编译期间完成分配，当进入一个方法时，这个方法需要在栈帧中分配多大的局部变量空间是完全确定的，在方法运行期间不会改变局部变量表的大小<sup class="footnote-ref"><a href="#fn3" id="fnref3">[3]</a></sup>。<br>
  如果线程请求的栈深度大于虚拟机所允许的深度，将抛出<code>StackOverflowError</code>异常；如果Java虚拟机栈容量可以动态扩展，当栈扩展时无法申请到足够的内存会抛出<code>OutOfMemoryError</code>异常。</p>
<ul>
<li>
<h4 id="本地方法栈">本地方法栈</h4>
</li>
</ul>
<blockquote>
<p>定义：Native Method Stacks与虚拟机栈所发挥的作用是非常相似的，其区别只是虚拟机栈为虚拟机执行Java方法（也就是字节码）服务，而本地方法栈则是为虚拟机使用到的本地（Native）方法服务。</p>
</blockquote>
<p>  无强制规定，可将其与虚拟机栈合二为一，如HotSpot VM;栈深度溢出或者栈扩展失败时分别抛出<code>StackOverflowError</code>和<code>OutOfMemoryError</code>异常。</p>
<ul>
<li>
<h4 id="java堆">Java堆</h4>
</li>
</ul>
<blockquote>
<p>定义：Java Heap是虚拟机所管理的内存中最大的一块，是被所有线程共享的一块内存区域，在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例，几乎所有的对象实例都在这里分配内存。</p>
</blockquote>
<p>  Java堆是垃圾收集器管理的内存区域，也被称作“GC堆”。从回收内存的角度看，由于现代垃圾收集器大部分都是基于分代收集理论设计的<sup class="footnote-ref"><a href="#fn4" id="fnref4">[4]</a></sup>.从分配内存的角度看，所有线程共享的Java堆中可以划分出多个线程私有的分配缓冲区（Thread LocalAllocation Buffer，TLAB），以提升对象分配时的效率。不过无论从什么角度，无论如何划分，都不会改变Java堆中存储内容的共性，无论是哪个区域，存储的都只能是对象的实例，将Java堆细分的目的只是为了更好地回收内存，或者更快地分配内存。<br>
  Java堆可以处于物理上不连续的内存空间中，但在逻辑上它应该被视为连续的，这点就像我们用磁盘空间去存储文件一样，并不要求每个文件都连续存放。但对于大对象（典型的如数组对象），多数虚拟机实现出于实现简单、存储高效的考虑，很可能会要求连续的内存空间。Java堆既可以被实现成固定大小的，也可以是可扩展的，不过当前主流的Java虚拟机都是按照可扩展来实现的（通过参数-Xmx和-Xms设定）。如果在Java堆中没有内存完成实例分配，并且堆也无法再扩展时，Java虚拟机将会抛出<code>OutOfMemoryError</code>异常。</p>
<ul>
<li>
<h4 id="方法区">方法区</h4>
</li>
</ul>
<blockquote>
<p>定义：各个线程共享的内存区域，它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。虽然《Java虚拟机规范》中把方法区描述为堆的一个逻辑部分，但是它却有一个别名叫作“非堆”（Non-Heap），目的是与Java堆区分开来。</p>
</blockquote>
<p>  除了和Java堆一样不需要连续的内存和可以选择固定大小或者可扩展外，甚至还可以选择不实现垃圾收集。相对而言，垃圾收集行为在这个区域的确是比较少出现的，但并非数据进入了方法区就如永久代的名字一样“永久”存在了。这区域的内存回收目标主要是针对常量池的回收和对类型的卸载，一般来说这个区域的回收效果比较难令人满意，尤其是类型的卸载，条件相当苛刻，但是这部分区域的回收有时又确实是必要的。以前Sun公司的Bug列表中，曾出现过的若干个严重的Bug就是由于低版本的HotSpot虚拟机对此区域未完全回收而导致内存泄漏。如果方法区无法满足新的内存分配需求时，将抛出OutOfMemoryError异常。</p>
<ul>
<li>
<h4 id="运行时常量池">运行时常量池</h4>
</li>
</ul>
<blockquote>
<p>定义：行时常量池（Runtime Constant Pool）是方法区的一部分。</p>
</blockquote>
<p>  Class文件中除了有类的版本、字段、方法、接口等描述信息外，还有一项信息是常量池表（Constant PoolTable），用于存放编译期生成的各种字面量与符号引用，这部分内容将在类加载后存放到方法区的运行时常量池中<sup class="footnote-ref"><a href="#fn5" id="fnref5">[5]</a></sup>。运行时常量池相对于Class文件常量池的另外一个重要特征是具备动态性，Java语言并不要求常量一定只有编译期才能产生，也就是说，并非预置入Class文件中常量池的内容才能进入方法区运行时常量池，运行期间也可以将新的常量放入池中，这种特性被开发人员利用得比较多的便是String类的intern()方法。既然运行时常量池是方法区的一部分，自然受到方法区内存的限制，当常量池无法再申请到内存时会抛出<code>OutOfMemoryError</code>异常。</p>
<ul>
<li>
<h4 id="直接内存"><em>直接内存</em></h4>
</li>
</ul>
<blockquote>
<p>定义：直接内存（Direct Memory）并不是虚拟机运行时数据区的一部分，也不是《Java虚拟机规范》中定义的内存区域。但是这部分内存也被频繁地使用，而且也可能导致<code>OutOfMemoryError</code>。</p>
</blockquote>
<p>  显然，本机直接内存的分配不会受到Java堆大小的限制，但是，既然是内存，则肯定还是会受到本机总内存（包括物理内存、SWAP分区或者分页文件）大小以及处理器寻址空间的限制，一般服务器管理员配置虚拟机参数时，会根据实际内存去设置-Xmx等参数信息，但经常忽略掉直接内存，使得各个内存区域总和大于物理内存限制（包括物理的和操作系统级的限制），从而导致动态扩展时出现<code>OutOfMemoryError</code>异常。</p>
<blockquote>
<p>参考：深入理解Java虚拟机：JVM高级特性与最佳实践（第3版） 周志明</p>
</blockquote>
<hr class="footnotes-sep">
<section class="footnotes">
<ol class="footnotes-list">
<li id="fn1" class="footnote-item"><p>通常所说的内存区的&quot;栈”就是指这里讲的虚拟机栈，或者更多的情况下只是指虚拟机栈中局部变量表部分。 <a href="#fnref1" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn2" class="footnote-item"><p>局部变量表存放了编译期可知的各种Java虚拟机基本数据类型，对象引用，returnAddress类型。 <a href="#fnref2" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn3" class="footnote-item"><p>这里说的“大小”是指变量槽的数量，虚拟机真正使用多大的内存空间（譬如按照1个变量槽占用32个比特、64个比特，或者更多）来实现一个变量槽，这是完全由具体的虚拟机实现自行决定的事情。 <a href="#fnref3" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn4" class="footnote-item"><p>Java堆中经常会出现“新生代”“老年代”“永久代”“Eden空间”“From Survivor空间”“To Survivor空间”等名词，这些区域划分仅仅是一部分垃圾收集器的共同特性或者说设计风格而已，而非某个Java虚拟机具体实现的固有内存布局，更不是《Java虚拟机规范》里对Java堆的进一步细致划分。不少资料上经常写着类似于“Java虚拟机的堆内存分为新生代、老年代、永久代、Eden、Survivor……”这样的内容。在十年之前（以G1收集器的出现为分界），作为业界绝对主流的HotSpot虚拟机，它内部的垃圾收集器全部都基于“经典分代”来设计，需要新生代、老年代收集器搭配才能工作，在这种背景下，上述说法还算是不会产生太大歧义。但是到了今天，垃圾收集器技术与十年前已不可同日而语，HotSpot里面也出现了不采用分代设计的新垃圾收集器，再按照上面的提法就有很多需要商榷的地方了。 <a href="#fnref4" class="footnote-backref">↩︎</a></p>
</li>
<li id="fn5" class="footnote-item"><p>Java虚拟机对于Class文件每一部分（自然也包括常量池）的格式都有严格规定，如每一个字节用于存储哪种数据都必须符合规范上的要求才会被虚拟机认可、加载和执行，但对于运行时常量池，《Java虚拟机规范》并没有做任何细节的要求，不同提供商实现的虚拟机可以按照自己的需要来实现这个内存区域，不过一般来说，除了保存Class文件中描述的符号引用外，还会把由符号引用翻译出来的直接引用也存储在运行时常量池中。 <a href="#fnref5" class="footnote-backref">↩︎</a></p>
</li>
</ol>
</section>

        </div>
        <!-- Share to Twitter, Weibo, Telegram -->
        <div class="flex items-center">
          <div class="mr-4 flex items-center">
            <i class="ri-share-forward-line text-gray-500"></i>
          </div>
          <div class="px-4 cursor-pointer text-blue-500 hover:bg-blue-100 dark:hover:bg-gray-600 inline-flex" @click="shareToTwitter">
            <i class="ri-twitter-line"></i>
          </div>
          <div class="px-4 cursor-pointer text-red-500 hover:bg-red-100 dark:hover:bg-gray-600 inline-flex" @click="shareToWeibo">
            <i class="ri-weibo-line"></i>
          </div>
          <div class="px-4 cursor-pointer text-indigo-500 hover:bg-indigo-100 dark:hover:bg-gray-600 inline-flex" @click="shareToTelegram">
            <i class="ri-telegram-line"></i>
          </div>
        </div>
      </div>

      
        
          <div id="gitalk-container"></div>
        

        
      

      
        <div id="vlaine-comment"></div>
      

      <footer class="py-12 text-center px-4 md:px-0" v-pre>
  Powered by <a href="https://github.com/getgridea/gridea" target="_blank">Gridea</a>  Made by  <a href="https://github.com/JoyZgq" target="_blank">zgq</a> 🎈❤❤❤🌹
</footer>
    </div>

    <!-- TOC Container -->
    <div class="fixed right-0 bottom-0 mb-16 mr-4 shadow w-8 h-8 rounded-full flex justify-center items-center z-10 cursor-pointer bg-white dark:bg-gray-500 dark:text-gray-200 hover:shadow-lg transition-all animated fadeInRight" @click="showToc = true">
      <i class="ri-file-list-line"></i>
    </div>

    <div class="fixed right-0 top-0 bottom-0 overflow-y-auto w-64 bg-white dark:bg-gray-800 p-4 border-l border-gray-100 dark:border-gray-600 z-10 transition-fast" :class="{ '-mr-64': !showToc }">
      <div class="flex mb-4 justify-end">
        <div class="w-8 h-8 inline-flex justify-center items-center rounded-full cursor-pointer hover:bg-gray-200 dark:hover:bg-gray-600 transition-fast" @click="showToc = false">
          <i class="ri-close-line text-lg"></i>
        </div>
      </div>
      <div class="post-toc-container">
        <ul class="markdownIt-TOC">
<li>
<ul>
<li>
<ul>
<li><a href="#%E8%BF%90%E8%A1%8C%E6%97%B6%E6%95%B0%E6%8D%AE%E5%8C%BA">运行时数据区</a>
<ul>
<li><a href="#%E7%A8%8B%E5%BA%8F%E8%AE%A1%E6%95%B0%E5%99%A8">程序计数器</a></li>
<li><a href="#java%E8%99%9A%E6%8B%9F%E6%9C%BA%E6%A0%88">Java虚拟机栈</a></li>
<li><a href="#%E6%9C%AC%E5%9C%B0%E6%96%B9%E6%B3%95%E6%A0%88">本地方法栈</a></li>
<li><a href="#java%E5%A0%86">Java堆</a></li>
<li><a href="#%E6%96%B9%E6%B3%95%E5%8C%BA">方法区</a></li>
<li><a href="#%E8%BF%90%E8%A1%8C%E6%97%B6%E5%B8%B8%E9%87%8F%E6%B1%A0">运行时常量池</a></li>
<li><a href="#%E7%9B%B4%E6%8E%A5%E5%86%85%E5%AD%98"><em>直接内存</em></a></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>

      </div>
    </div>

    <!-- Back to top -->
    <div class="fixed right-0 bottom-0 mb-4 mr-4 shadow w-8 h-8 rounded-full flex justify-center items-center z-10 cursor-pointer bg-white hover:shadow-lg transition-all dark:bg-gray-500 dark:text-gray-200" @click="backToUp" v-show="scrolled">
      <i class="ri-arrow-up-line"></i>
    </div>
  </div>

  <!-- Root element of PhotoSwipe. Must have class pswp. -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
  <!-- Background of PhotoSwipe. 
        It's a separate element as animating opacity is faster than rgba(). -->
  <div class="pswp__bg">
  </div>
  <!-- Slides wrapper with overflow:hidden. -->
  <div class="pswp__scroll-wrap">
    <!-- Container that holds slides. 
            PhotoSwipe keeps only 3 of them in the DOM to save memory.
            Don't modify these 3 pswp__item elements, data is added later on. -->
    <div class="pswp__container">
      <div class="pswp__item">
      </div>
      <div class="pswp__item">
      </div>
      <div class="pswp__item">
      </div>
    </div>
    <!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
    <div class="pswp__ui pswp__ui--hidden">
      <div class="pswp__top-bar">
        <!--  Controls are self-explanatory. Order can be changed. -->
        <div class="pswp__counter">
        </div>
        <button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
        <button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
        <button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
        <!-- Preloader demo http://codepen.io/dimsemenov/pen/yyBWoR -->
        <!-- element will get class pswp__preloader--active when preloader is running -->
        <div class="pswp__preloader">
          <div class="pswp__preloader__icn">
            <div class="pswp__preloader__cut">
              <div class="pswp__preloader__donut">
              </div>
            </div>
          </div>
        </div>
      </div>
      <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
        <div class="pswp__share-tooltip">
        </div>
      </div>
      <button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
      </button>
      <button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
      </button>
      <div class="pswp__caption">
        <div class="pswp__caption__center">
        </div>
      </div>
    </div>
  </div>
</div>

  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script src="https://JoyZgq.github.io/media/scripts/main.js"></script>
  
  <!-- Code Highlight -->
  
    <script src="https://JoyZgq.github.io/media/prism.js"></script>
    <script>
      Prism.highlightAll()
    </script>
  

  <script src="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe-ui-default.min.js"></script>
  <script>
    //拿到预览框架，也就是上面的html代码
    var pswpElement = document.querySelectorAll('.pswp')[0];
    //定义图片数组变量
    var imgitems;
    /**
    * 用于显示预览界面
    * @param index 图片数组下标
    */
    function viewImg(index) {
      //其它选项这里不做过多阐述，详情见官网
      var pswpoptions = {
        index: parseInt(index, 10), // 开始幻灯片索引。0是第一张幻灯片。必须是整数，而不是字符串。
        bgOpacity: 0.7, // 背景透明度，0-1
        maxSpreadZoom: 3, // 缩放级别，不要太大
      };
      //初始化并打开PhotoSwipe，pswpElement对应上面预览框架，PhotoSwipeUI_Default为皮肤，imgitems为图片数组，pswpoptions为选项
      var gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, imgitems, pswpoptions);
      gallery.init()
    }
    /**
    * 用于添加图片点击事件
    * @param img 图片元素
    * @param index 所属下标（在imgitems中的位置）
    */
    function addImgClick(img, index) {
      img.onclick = function() {
        viewImg(index)
      }
    }
    /**
    * 轮询所有图片，获取src、width、height等数据，加入imgitems，并给图片元素添加事件
    * 最好在onload中执行该方法，本站因放在最底部，所以直接初始化
    * 异步加载图片可在图片元素创建完成后调用此方法
    */
    function initImg() {
      //重置图片数组
      imgitems = [];
      //查找class:markdown 下的所有img元素并遍历
      var imgs = document.querySelectorAll('.markdown img');
      for (var i = 0; i < imgs.length; i++) {
        var img = imgs[i];
        //本站相册初始为loading图片，真实图片放在data-src
        var ds = img.getAttribute("data-src");
        //创建image对象，用于获取图片宽高
        var imgtemp = new Image();
        //判断是否存在data-src
        if (ds != null && ds.length > 0) {
          imgtemp.src = ds
        } else {
          imgtemp.src = img.src
        }
        //判断是否存在缓存
        if (imgtemp.complete) {
          var imgobj = {
            "src": imgtemp.src,
            "w": imgtemp.width,
            "h": imgtemp.height,
          };
          imgitems[i] = imgobj;
          addImgClick(img, i);
        } else {
          console.log('进来了2')
          imgtemp.index = i;
          imgtemp.img = img;
          imgtemp.onload = function() {
            var imgobj = {
              "src": this.src,
              "w": this.width,
              "h": this.height,
            };
            //不要使用push，因为onload前后顺序会不同
            imgitems[this.index] = imgobj
            //添加点击事件
            addImgClick(this.img, this.index);
          }
        }
      }
    }
    //初始化
    initImg();
  </script>
  
    <script type="application/javascript" src="https://unpkg.com/valine"></script>
<script type="application/javascript">
  new Valine({
    el: '#vlaine-comment',
    appId: 'Sy2gsMvGcPQl3gTGsqqYsHW6-gzGzoHsz',
    appKey: 'IpsgegiMUNgRg7l5BVXk6EXM',
    pageSize: 10,
    notify: false,
    avatar: 'mp',
    verify: true,
    placeholder: '客官来都来了，不妨评论一下🌹🐱‍👤',
    visitor: true,
    highlight: false,
    recordIP: true,
  })
</script>
  
  
    
      <link rel="stylesheet" href="https://unpkg.com/gitalk/dist/gitalk.css">
<script type="application/javascript" src="https://unpkg.com/gitalk/dist/gitalk.min.js"></script>

<script type="application/javascript">

  var gitalk = new Gitalk({
    clientID: '83da62f594c23db993f3',
    clientSecret: '9aa795ad06ecb4133721f1acf047ecb1e4f295e8',
    repo: 'GitalkApp',
    owner: 'JoyZgq',
    admin: ['JoyZgq'],
    id: (location.pathname).substring(0, 49),      // Ensure uniqueness and length less than 50
    distractionFreeMode: false  // Facebook-like distraction free mode
  })

  gitalk.render('gitalk-container')

</script>

    
  
</body>

</html>